<?php

namespace Application\System\Controller;

use Aoe\Core\Module;
use Aoe\Emulator\Controller\Aoe;
use Aoe\Intent\Request\Request;
use Aoe\Util\Bus\Config\Config;
use Application\System\Controller\X\Dms;
use Application\System\Controller\X\Standard;
use Exception;
use Throwable;

/**
 * # 模块安装与下载
 *
 * @noinspection PhpUnused
 */
class Install extends Aoe
{
    const string INSTALL = 'install';

    protected function get_core_method_name(Request $request): string
    {
        return '_invoke_';
    }

    /**
     * @param Request $request
     * @return void
     * @noinspection PhpUnusedPrivateMethodInspection
     */
    private function _invoke_(Request $request): void
    {
        try {
            // 重定向Module
            $this->module = $this->kernel->getModule($request->getParam('module'));
            $request->getParam('uninstall') ? $this->_uninstall_($request) : $this->_install_($request);
        } catch (Throwable) {
            $request->response->error('请先将模块文件夹复制到应用目录下');
        }
    }

    private function _uninstall_(Request $request): void
    {
        try {
            $this->_make_and_run_sql(false);
        } catch (Exception $e) {
            $request->response->error($this->recorder->Error($e->getMessage()));
        }

        $request->response->ok('卸载完成');
    }

    private function _install_(Request $request): void
    {
        try {
            $this->_make_and_run_sql();
        } catch (Throwable $e) {
            $request->response->error($this->recorder->Error($e->getMessage()));
            return;
        }

        $config = $this->module->config;

        $this->_install_values($config, $request);
        $this->_install_authorize($config, $request);

        $request->response->ok('安装完成');
    }

    /** @noinspection PhpUnused */

    /**
     * @throws Exception
     */
    private function _make_and_run_sql(bool $install = true): void
    {
        // 创建SQL语句
        $tables = Standard::sql($this->kernel->Smart()->getModelsOf($this->module), $install);
        Dms::execute($this->get_database(), $tables, $install);
    }

    private function _install_values(Config $config, Request $request): void
    {
        $install = $config->get(self::INSTALL, false);
        if (empty($install)) return;

        if (isset($install['values'])) $this->_add_values($install['values']);
        if (isset($install['commands'])) $this->_run_commands($install['commands'], $request);
    }

    private function _add_values($values): void
    {
        if (empty($values) || !is_array($values)) return;

        foreach ($values as $collection => $rows) {
            foreach ($rows as $row) {
                try {
                    $this->create_entity($collection)->insert($row);
                } catch (Throwable) {
                }
            }
        }
    }

    private function _run_commands($commands, Request $request): void
    {
        if (empty($commands) || !is_array($commands)) return;

        foreach ($commands as $command => $params) $request->channel($command, $params);
    }

    private function _install_authorize(Config $config, Request $request): void
    {
        if (!$config->get('auth', true)) return;
        $controllers = $config->get(Module::KEY_CONTROLLERS, []);
        if (empty($controllers)) return;

        $request->channel(AUTH_CMD, [
            'controllers' => array_map(fn(array $c) => ['name' => $c['name'], 'label' => $c['label']], $controllers),
            'module' => ['name' => $this->module, 'label' => $this->module->label]
        ]);
    }
}